/*
 * Copyright (c) 2007 Sun Microsystems, Inc.
 * Copyright (c) 2010 Oracle
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

package ritcs.sensors.app;

import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.peripheral.NoAckException;

import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.microedition.io.*;

import javax.swing.*;

/**
 * Simple example class to locate a remote service (on a SPOT), to connect to it
 * and send it a variety of commands. In this case to set or calibrate the SPOT's
 * accelerometer and to return a stream of accelerometer telemetry information. 
 *
 * @author Ron Goldman<br>
 * Date: May 2, 2006<br>
 * Modified: August 1, 2010
 */
public class Listener extends Thread implements PacketTypes {
        

    private String ieee;
    private RadiogramConnection conn = null;
    private Radiogram xdg = null;
    private boolean running = true;
    private long timeStampOffset = -1;
    private int index = 0;

    private Database dbHandler;
    private ApplicationWindow window;
    
    

    /**
     * Create a new AccelerometerListener to connect to the remote SPOT over the radio.
     */
    public Listener (String ieee, Database dbHandler) {
        this.ieee = ieee;
        final String intieee=  ieee;
        this.dbHandler = dbHandler;
        
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
        window = new ApplicationWindow(intieee,Listener.this);


                window.setVisible(true);
            }
        });
    }
    

    
    /**
     * Send a request to the remote SPOT to set which accelerometer scale it will use.
     *
     * @param val the scale to use: (2 or 6) or (2, 4 or 8)
     */

    public void doSetPeriod(int period){
        sendCmd(SET_PERIOD, period);


    }
    /**
     * Send a request to the remote SPOT to start or stop sending accelerometer readings.
     *
     * @param sendIt true to start sending, false to stop
     * @param gView the GraphView display to pass the data to
     */
    public void doSendData (boolean sendIt) {
//        graphView = gView;
        sendCmd(sendIt ? SEND_ACCEL_DATA_REQ : STOP_ACCEL_DATA_REQ);
    }

    /**
     * Send a request to the remote SPOT to report on radio signal strength.
     */
    public void doPing() {
        sendCmd(PING_REQ);
    }

    /**
     * Send a request to the remote SPOT to blink its LEDs.
     */
    public void doBlink() {
        sendCmd(BLINK_LEDS_REQ);
    }

    /**
     * Send a request to the remote SPOT to reconnect.
     */
    public void reconnect() {
        
        sendCmd(DISPLAY_SERVER_RESTART);
    }

    public void getGUIParams(){
        sendCmd(GET_GUI_INFO);
    }



    /**
     * Stop running. Also notify the remote SPOT that we are no longer listening to it.
     */

    public void doQuit () {
        if (conn != null) {
            sendCmd(DISPLAY_SERVER_QUITTING);
            try {
                conn.close();
            } catch (IOException ex) {
                System.out.println("Error closing connection to SPOT " + ieee);
            }
            conn = null;
        }
        running = false;
    }

    /**
     * Send a simple command request to the remote SPOT.
     *
     * @param cmd the command requested
     */
    private void sendCmd (byte cmd) {
        if (conn != null) {
            try {
                xdg.reset();
                xdg.writeByte(cmd);
                
                conn.send(xdg);
            } catch (NoAckException nex) {

            } catch (IOException ex) {
                // ignore any other problems
            }
        }
    }

     private void sendCmd (byte cmd, int net) {
        if (conn != null) {
            try {
                xdg.reset();
                xdg.writeByte(cmd);
                if(cmd == GET_TEMPERATURE || cmd == SET_PERIOD)
                    xdg.writeInt(net);
                

                conn.send(xdg);
            } catch (NoAckException nex) {

            } catch (IOException ex) {
                // ignore any other problems
            }
        }
    }

public void getTemperature(int network){


    sendCmd(GET_TEMPERATURE, 3);
}

    /**
     * Routine to reset after old data has been cleared from the GUI display.
     */
    public void clear () {
        index = 0;
        timeStampOffset = -1;
    }

        
    /**
     * Main runtime loop to connect to a remote SPOT.
     * Do not call directly. Call start() instead.
     */
    public void run () {
        running = true;
        try {
            conn = (RadiogramConnection) Connector.open("radiogram://" + ieee + ":" + CONNECTED_PORT);
            //System.out.print("Connected");
            Radiogram rdg = (Radiogram) conn.newDatagram(conn.getMaximumLength());
            xdg = (Radiogram) conn.newDatagram(10); // we never send more than 1 or 2 bytes
            index = 0;
            timeStampOffset = -1;
            while (running) {
                try {
                    conn.receive(rdg);            // wait until we receive a reply
                } catch (IOException ex) {
                    continue;
                }
                byte packetType = rdg.readByte();
                switch (packetType) {
                   
                    case PING_REPLY:
                        System.out.println("Ping reply:  (linkQuality : corr : rssi)");
                        System.out.println("   host->spot: " + rdg.readInt() + " : " + rdg.readInt() + " : " + rdg.readInt());
                        System.out.println("   spot->host: " + rdg.getLinkQuality() + " : " + rdg.getCorr() + " : " + rdg.getRssi());
                        System.out.println("   spot battery voltage: " + rdg.readInt() + " mv");
                        break;
                    case MESSAGE_REPLY:
                        String str = rdg.readUTF();
                        System.out.println("Message from sensor: " + str);
                        break;
                    case GET_TEMPERATURE_REPLY:
                        double d = rdg.readDouble();
                        long time = rdg.readLong();
                        int network = rdg.readInt();
                        double light = rdg.readDouble();
                        String addr = rdg.getAddress();
                        Date da = new Date(time);
                        System.out.println("Received from "+addr+ " at "+da + " for network: "+network);
                        dbHandler.recordReading(new java.sql.Timestamp(time), (float)d,(float) light);
                        
                        break;
                    case GET_GUI_INFO_REPLY:
                        System.out.println("Here");
                        int batt = rdg.readInt();
                        int link = rdg.readInt();
                        int rev = rdg.getLinkQuality();

                        window.setBattery(batt);

                        window.setLinkQuality(link);
                        window.setReverseQuality(rev);
                        break;


                }
            }
        } catch (Exception ex) {
            System.out.println("Error communicating with remote Spot: ");
            ex.printStackTrace();
        } finally {
            try {

                if (conn != null) {
                    xdg.reset();
                    xdg.writeByte(DISPLAY_SERVER_QUITTING);        // packet type
                    conn.send(xdg);                                // broadcast it
                    conn.close();
                    conn = null;
                }
            } catch (IOException ex) { /* ignore */ }
        }
    }

}
